# Dependencias básicas
import pandas as pd
import numpy as np
import itertools
# Dependencias de visualización
from matplotlib import pyplot as plt
import seaborn as sns
import altair as alt
# Desactivar el límite de máximo por defecto de 5,000 filas para las visulizaciones con la librería Altair
alt.data_transformers.disable_max_rows()
# Despendencias estadísticas
import scipy.stats as stats
#!pip install scikit-posthocs
import scikit_posthocs as sp
# Importación de datasets
inmigrantes_data = pd.read_csv("../13 - Exports (preprocesamiento)/top_inmigracion_2008_2022.csv")
indices_democracia = pd.read_csv("../13 - Exports (preprocesamiento)/indices_democracia.csv")
indices_desarrollo = pd.read_csv("../13 - Exports (preprocesamiento)/indices_desarrollo.csv")
regiones = pd.read_csv("../13 - Exports (preprocesamiento)/continentes_regiones.csv")
libertad = pd.read_csv("../13 - Exports (preprocesamiento)/libertad.csv")
conflictos_armados = pd.read_csv("../13 - Exports (preprocesamiento)/muertes_conflictos_armados.csv")
residentes = pd.read_csv("../13 - Exports (preprocesamiento)/residentes.csv")
regimen_politico = pd.read_csv("../13 - Exports (preprocesamiento)/regimen_politico.csv")
homicidios = pd.read_csv("../13 - Exports (preprocesamiento)/tasa_homicidios.csv")
turismo = pd.read_csv("../13 - Exports (preprocesamiento)/turismo.csv")
# Lista con todos los df
dataframes = [inmigrantes_data, indices_democracia, indices_desarrollo, regiones, libertad, conflictos_armados, residentes, regimen_politico, homicidios, turismo]
# Funcion para obtener el nombre de cada dataframe
def get_df_name(df):
name =[x for x in globals() if globals()[x] is df][0]
return name
# Bucle para mostrar por pantalla cada dataframe
with pd.option_context('expand_frame_repr', False): # expandir las columnas del output
for df in dataframes:
print (f'------------->>>>>>>>>>> {get_df_name(df)} <<<<<<<<<<<<----------------\n')
print (df)
print ('\n')
------------->>>>>>>>>>> inmigrantes_data <<<<<<<<<<<<----------------
Year Nationality code Sex Age group Immigrant count
0 2008 DZA Both 0 - 14 759
1 2008 PER Males 35 - 44 2938
2 2008 PER Males 45 - 54 1128
3 2008 PER Males 55 - 64 265
4 2008 PER Males 65+ 156
... ... ... ... ... ...
9355 2022 PAK Males 55 - 64 330
9356 2022 PAK Females 55 - 64 146
9357 2022 PAK Both 65+ 169
9358 2022 PAK Males 65+ 99
9359 2022 PAK Females 65+ 70
[9360 rows x 5 columns]
------------->>>>>>>>>>> indices_democracia <<<<<<<<<<<<----------------
Nationality code Year Liberal democracy index Deliberative democracy index
0 DZA 2008 0.164 0.249
1 DZA 2009 0.163 0.246
2 DZA 2010 0.162 0.250
3 DZA 2011 0.162 0.250
4 DZA 2012 0.165 0.252
.. ... ... ... ...
400 VEN 2018 0.060 0.040
401 VEN 2019 0.059 0.041
402 VEN 2020 0.057 0.040
403 VEN 2021 0.060 0.045
404 VEN 2022 0.056 0.044
[405 rows x 4 columns]
------------->>>>>>>>>>> indices_desarrollo <<<<<<<<<<<<----------------
Year Nationality code Unemployment % Political and Violence Percentile Probability of dying young Regulatory Quality Percentile Rule of Law Percentile Voice and Accountability Percentile Salaried workers % GDP_growth Inflation_annual
0 2008 DZA 11.33 14.90 3.7 29.13 24.52 20.67 67.41 2.40 15.31
1 2008 ARG 7.84 40.87 4.8 24.76 27.88 58.17 76.32 4.06 23.17
2 2008 BRA 8.27 33.65 8.1 54.37 46.63 63.94 66.28 5.09 8.78
3 2008 BGR 5.61 56.25 3.7 73.30 51.92 65.87 87.60 6.13 8.10
4 2008 CHN 4.59 29.33 2.9 48.54 37.98 5.77 45.96 9.65 7.80
.. ... ... ... ... ... ... ... ... ... ... ...
400 2022 ESP 12.92 53.30 1.5 75.94 77.36 79.71 84.66 5.77 4.14
401 2022 UKR 33.30 5.66 18.1 40.57 18.87 45.89 82.40 -29.10 34.32
402 2022 GBR 3.73 62.26 1.7 93.40 89.15 89.37 84.33 4.35 5.15
403 2022 USA 3.65 45.28 6.2 91.04 88.68 72.95 93.72 1.94 7.04
404 2022 VEN 5.62 12.26 15.5 2.36 0.47 6.76 59.85 8.00 1203.15
[405 rows x 11 columns]
------------->>>>>>>>>>> regiones <<<<<<<<<<<<----------------
Continent Sub-region Nationality code
0 Europe European Union BGR
1 Europe European Union FRA
2 Europe European Union ITA
3 Europe European Union PRT
4 Europe European Union DEU
5 Europe European Union ROU
6 Europe Rest of Europe GBR
7 Europe Rest of Europe UKR
8 Europe Rest of Europe RUS
9 Africa Africa DZA
10 Africa Africa MAR
11 Africa Africa SEN
12 America North America USA
13 America Central America and Caribbean CUB
14 America Central America and Caribbean HND
15 America Central America and Caribbean NIC
16 America Central America and Caribbean DOM
17 America South America ARG
18 America South America BRA
19 America South America COL
20 America South America ECU
21 America South America PRY
22 America South America PER
23 America South America VEN
24 Asia Asia CHN
25 Asia Asia PAK
------------->>>>>>>>>>> libertad <<<<<<<<<<<<----------------
Country code Year Absence of Corruption Civil Liberties Educational equality Health equality Judicial accountability Public sector corrupt exchanges
0 ARG 2008 0.51 0.80 0.56 0.62 0.37 0.46
1 ARG 2009 0.51 0.80 0.56 0.62 0.37 0.46
2 ARG 2010 0.51 0.80 0.56 0.62 0.37 0.46
3 ARG 2011 0.51 0.80 0.56 0.62 0.37 0.46
4 ARG 2012 0.49 0.80 0.56 0.62 0.37 0.46
.. ... ... ... ... ... ... ... ...
385 VEN 2018 0.06 0.39 0.23 0.18 0.01 0.00
386 VEN 2019 0.06 0.37 0.18 0.18 0.01 0.00
387 VEN 2020 0.00 0.37 0.13 0.18 0.12 0.00
388 VEN 2021 0.00 0.37 0.17 0.18 0.07 0.00
389 VEN 2022 0.00 0.37 0.13 0.05 0.07 0.00
[390 rows x 8 columns]
------------->>>>>>>>>>> conflictos_armados <<<<<<<<<<<<----------------
Nationality code Year One-sided violence_deaths Non-state_deaths Intrastate_deaths Interstate_deaths
0 DZA 2008 0 0 345 0
1 DZA 2009 36 0 508 0
2 DZA 2010 0 0 236 0
3 DZA 2011 0 0 261 0
4 DZA 2012 0 0 258 0
.. ... ... ... ... ... ...
400 VEN 2018 89 0 2 0
401 VEN 2019 78 0 7 0
402 VEN 2020 0 0 0 0
403 VEN 2021 0 0 3 0
404 VEN 2022 0 2 0 0
[405 rows x 6 columns]
------------->>>>>>>>>>> residentes <<<<<<<<<<<<----------------
Country Code Year Sex Number of residents
0 DEU 2022 Both 116122
1 DEU 2021 Both 109556
2 DEU 2020 Both 111937
3 DEU 2019 Both 111911
4 DEU 2018 Both 111495
... ... ... ... ...
1945 PAK 2002 Females 1521
1946 PAK 2001 Females 1138
1947 PAK 2000 Females 882
1948 PAK 1999 Females 740
1949 PAK 1998 Females 572
[1950 rows x 4 columns]
------------->>>>>>>>>>> regimen_politico <<<<<<<<<<<<----------------
Nationality code Year Political regime
0 DZA 2008 3
1 DZA 2009 3
2 DZA 2010 3
3 DZA 2011 3
4 DZA 2012 3
.. ... ... ...
400 VEN 2018 1
401 VEN 2019 1
402 VEN 2020 1
403 VEN 2021 1
404 VEN 2022 1
[405 rows x 3 columns]
------------->>>>>>>>>>> homicidios <<<<<<<<<<<<----------------
Year Nationality code Homicide Rate
0 2008 ARG 5.89
1 2008 BGR 2.24
2 2008 BRA 26.02
3 2008 CHN 1.11
4 2008 COL 36.84
.. ... ... ...
393 2022 UKR 3.86
394 2015 SEN 0.27
395 2020 NIC 9.37
396 2022 NIC 11.40
397 2015 DOM 16.48
[398 rows x 3 columns]
------------->>>>>>>>>>> turismo <<<<<<<<<<<<----------------
Year Number of Turist
0 2000 34380000
1 2001 35330000
2 2002 34950000
3 2003 36920000
4 2004 38520000
5 2005 40730000
6 2006 42450000
7 2007 44320000
8 2008 44400000
9 2009 40230000
10 2010 40560000
11 2011 44610000
12 2012 46160000
13 2013 48760000
14 2014 51820000
15 2015 54280000
16 2016 60340000
17 2017 66640000
18 2018 67550000
19 2019 68690000
20 2020 13660000
21 2021 24430000
22 2022 59310000
23 2023 69560000
# Hacer una copia de datos de inmigrantes para los merge
inmigrantes = inmigrantes_data.copy()
inmigrantes
| Year | Nationality code | Sex | Age group | Immigrant count | |
|---|---|---|---|---|---|
| 0 | 2008 | DZA | Both | 0 - 14 | 759 |
| 1 | 2008 | PER | Males | 35 - 44 | 2938 |
| 2 | 2008 | PER | Males | 45 - 54 | 1128 |
| 3 | 2008 | PER | Males | 55 - 64 | 265 |
| 4 | 2008 | PER | Males | 65+ | 156 |
| ... | ... | ... | ... | ... | ... |
| 9355 | 2022 | PAK | Males | 55 - 64 | 330 |
| 9356 | 2022 | PAK | Females | 55 - 64 | 146 |
| 9357 | 2022 | PAK | Both | 65+ | 169 |
| 9358 | 2022 | PAK | Males | 65+ | 99 |
| 9359 | 2022 | PAK | Females | 65+ | 70 |
9360 rows × 5 columns
# Renombrar columna de codigo de país como el df "inmigrantes"
residentes.rename({'Country Code' : 'Nationality code'},
inplace = True,
axis = 1)
libertad.rename({'Country code' : 'Nationality code'},
inplace = True,
axis = 1)
# Merge cada df en "inmigrantes"
inmigrantes_merge = inmigrantes.merge(indices_desarrollo, on = ['Year', 'Nationality code'], how = 'left')\
.merge(indices_democracia, on = ['Year', 'Nationality code'], how = 'left')\
.merge(regiones, on = ['Nationality code'], how = 'left')\
.merge(libertad, on = ['Year', 'Nationality code'], how = 'left')\
.merge(conflictos_armados, on = ['Year', 'Nationality code'], how = 'left')\
.merge(residentes, on = ['Year', 'Nationality code', 'Sex'], how = 'left')\
.merge(regimen_politico, on = ['Year', 'Nationality code'], how = 'left')\
.merge(homicidios, on = ['Year', 'Nationality code'], how = 'left')\
.merge(turismo, on = ['Year'], how = 'left')\
inmigrantes_merge.info()
inmigrantes_merge.iloc[:, :15]
<class 'pandas.core.frame.DataFrame'> RangeIndex: 9360 entries, 0 to 9359 Data columns (total 32 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Year 9360 non-null int64 1 Nationality code 9360 non-null object 2 Sex 9360 non-null object 3 Age group 9360 non-null object 4 Immigrant count 9360 non-null int64 5 Unemployment % 9360 non-null float64 6 Political and Violence Percentile 9360 non-null float64 7 Probability of dying young 9360 non-null float64 8 Regulatory Quality Percentile 9360 non-null float64 9 Rule of Law Percentile 9360 non-null float64 10 Voice and Accountability Percentile 9360 non-null float64 11 Salaried workers % 9360 non-null float64 12 GDP_growth 9360 non-null float64 13 Inflation_annual 9360 non-null float64 14 Liberal democracy index 9360 non-null float64 15 Deliberative democracy index 9360 non-null float64 16 Continent 9360 non-null object 17 Sub-region 9360 non-null object 18 Absence of Corruption 9360 non-null float64 19 Civil Liberties 9360 non-null float64 20 Educational equality 9360 non-null float64 21 Health equality 9360 non-null float64 22 Judicial accountability 9360 non-null float64 23 Public sector corrupt exchanges 9360 non-null float64 24 One-sided violence_deaths 9360 non-null int64 25 Non-state_deaths 9360 non-null int64 26 Intrastate_deaths 9360 non-null int64 27 Interstate_deaths 9360 non-null int64 28 Number of residents 9360 non-null int64 29 Political regime 9360 non-null int64 30 Homicide Rate 9024 non-null float64 31 Number of Turist 9360 non-null int64 dtypes: float64(18), int64(9), object(5) memory usage: 2.3+ MB
| Year | Nationality code | Sex | Age group | Immigrant count | Unemployment % | Political and Violence Percentile | Probability of dying young | Regulatory Quality Percentile | Rule of Law Percentile | Voice and Accountability Percentile | Salaried workers % | GDP_growth | Inflation_annual | Liberal democracy index | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2008 | DZA | Both | 0 - 14 | 759 | 11.33 | 14.90 | 3.7 | 29.13 | 24.52 | 20.67 | 67.41 | 2.40 | 15.31 | 0.164 |
| 1 | 2008 | PER | Males | 35 - 44 | 2938 | 4.03 | 17.31 | 5.1 | 61.65 | 25.96 | 52.40 | 44.47 | 9.13 | 1.10 | 0.649 |
| 2 | 2008 | PER | Males | 45 - 54 | 1128 | 4.03 | 17.31 | 5.1 | 61.65 | 25.96 | 52.40 | 44.47 | 9.13 | 1.10 | 0.649 |
| 3 | 2008 | PER | Males | 55 - 64 | 265 | 4.03 | 17.31 | 5.1 | 61.65 | 25.96 | 52.40 | 44.47 | 9.13 | 1.10 | 0.649 |
| 4 | 2008 | PER | Males | 65+ | 156 | 4.03 | 17.31 | 5.1 | 61.65 | 25.96 | 52.40 | 44.47 | 9.13 | 1.10 | 0.649 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 9355 | 2022 | PAK | Males | 55 - 64 | 330 | 5.60 | 6.60 | 5.8 | 20.28 | 25.00 | 25.12 | 42.14 | 4.71 | 13.96 | 0.234 |
| 9356 | 2022 | PAK | Females | 55 - 64 | 146 | 5.60 | 6.60 | 5.8 | 20.28 | 25.00 | 25.12 | 42.14 | 4.71 | 13.96 | 0.234 |
| 9357 | 2022 | PAK | Both | 65+ | 169 | 5.60 | 6.60 | 5.8 | 20.28 | 25.00 | 25.12 | 42.14 | 4.71 | 13.96 | 0.234 |
| 9358 | 2022 | PAK | Males | 65+ | 99 | 5.60 | 6.60 | 5.8 | 20.28 | 25.00 | 25.12 | 42.14 | 4.71 | 13.96 | 0.234 |
| 9359 | 2022 | PAK | Females | 65+ | 70 | 5.60 | 6.60 | 5.8 | 20.28 | 25.00 | 25.12 | 42.14 | 4.71 | 13.96 | 0.234 |
9360 rows × 15 columns
inmigrantes_merge.iloc[:, 15:]
| Deliberative democracy index | Continent | Sub-region | Absence of Corruption | Civil Liberties | Educational equality | Health equality | Judicial accountability | Public sector corrupt exchanges | One-sided violence_deaths | Non-state_deaths | Intrastate_deaths | Interstate_deaths | Number of residents | Political regime | Homicide Rate | Number of Turist | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.249 | Africa | Africa | 0.38 | 0.49 | 0.59 | 0.61 | 0.39 | 0.35 | 0 | 0 | 345 | 0 | 51922 | 3 | 0.95 | 44400000 |
| 1 | 0.646 | America | South America | 0.49 | 0.72 | 0.35 | 0.40 | 0.44 | 0.30 | 0 | 0 | 40 | 0 | 60185 | 7 | 5.27 | 44400000 |
| 2 | 0.646 | America | South America | 0.49 | 0.72 | 0.35 | 0.40 | 0.44 | 0.30 | 0 | 0 | 40 | 0 | 60185 | 7 | 5.27 | 44400000 |
| 3 | 0.646 | America | South America | 0.49 | 0.72 | 0.35 | 0.40 | 0.44 | 0.30 | 0 | 0 | 40 | 0 | 60185 | 7 | 5.27 | 44400000 |
| 4 | 0.646 | America | South America | 0.49 | 0.72 | 0.35 | 0.40 | 0.44 | 0.30 | 0 | 0 | 40 | 0 | 60185 | 7 | 5.27 | 44400000 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 9355 | 0.301 | Asia | Asia | 0.36 | 0.48 | 0.18 | 0.27 | 0.22 | 0.23 | 68 | 0 | 670 | 0 | 68821 | 6 | 4.21 | 59310000 |
| 9356 | 0.301 | Asia | Asia | 0.36 | 0.48 | 0.18 | 0.27 | 0.22 | 0.23 | 68 | 0 | 670 | 0 | 31675 | 6 | 4.21 | 59310000 |
| 9357 | 0.301 | Asia | Asia | 0.36 | 0.48 | 0.18 | 0.27 | 0.22 | 0.23 | 68 | 0 | 670 | 0 | 100496 | 6 | 4.21 | 59310000 |
| 9358 | 0.301 | Asia | Asia | 0.36 | 0.48 | 0.18 | 0.27 | 0.22 | 0.23 | 68 | 0 | 670 | 0 | 68821 | 6 | 4.21 | 59310000 |
| 9359 | 0.301 | Asia | Asia | 0.36 | 0.48 | 0.18 | 0.27 | 0.22 | 0.23 | 68 | 0 | 670 | 0 | 31675 | 6 | 4.21 | 59310000 |
9360 rows × 17 columns
# Contar datos nulos
inmigrantes_merge.isnull().sum()
Year 0 Nationality code 0 Sex 0 Age group 0 Immigrant count 0 Unemployment % 0 Political and Violence Percentile 0 Probability of dying young 0 Regulatory Quality Percentile 0 Rule of Law Percentile 0 Voice and Accountability Percentile 0 Salaried workers % 0 GDP_growth 0 Inflation_annual 0 Liberal democracy index 0 Deliberative democracy index 0 Continent 0 Sub-region 0 Absence of Corruption 0 Civil Liberties 0 Educational equality 0 Health equality 0 Judicial accountability 0 Public sector corrupt exchanges 0 One-sided violence_deaths 0 Non-state_deaths 0 Intrastate_deaths 0 Interstate_deaths 0 Number of residents 0 Political regime 0 Homicide Rate 336 Number of Turist 0 dtype: int64
Como observamos en la Etapa 2, no se obtuvieron datos de homicidios para Senegal más que para el año 2015, y debido a la cantidad de datos faltantes, se decidió no imputarlos ya que algunos modelos de regresión, como los basados en árboles, aceptan datos nulos. Para el caso de modelos lineales, removerá a Senegal del conjunto de datos para realizar el modelo de machine learning.
Idioma Castellano
Esta variable categórica señala si el idioma castellano es el idioma oficial de un país (sí = 1, no = 0), y con ella se busva incluir el efecto del dominio del mismo idioma hablado en España sobre la desición preferente de este destino por los inmigrantes.
# Cargar datos de Inflación global/anual del banco mundial
spanish_language = pd.read_excel("../3 - Paises Idioma español oficial/paises_hispanohablantes.xlsx")
spanish_language
| Country | Country code | Spanish language | |
|---|---|---|---|
| 0 | Argentina | ARG | 1 |
| 1 | Bolivia | BOL | 1 |
| 2 | Chile | CHL | 1 |
| 3 | Colombia | COL | 1 |
| 4 | Costa Rica | CRI | 1 |
| 5 | Cuba | CUB | 1 |
| 6 | Ecuador | ECU | 1 |
| 7 | El Salvador | SLV | 1 |
| 8 | España | ESP | 1 |
| 9 | Guatemala | GTM | 1 |
| 10 | Guinea Ecuatorial | GNQ | 1 |
| 11 | Honduras | HND | 1 |
| 12 | México | MEX | 1 |
| 13 | Nicaragua | NIC | 1 |
| 14 | Panamá | PAN | 1 |
| 15 | Paraguay | PRY | 1 |
| 16 | Perú | PER | 1 |
| 17 | Puerto Rico | PR | 1 |
| 18 | República Dominicana | DOM | 1 |
| 19 | Uruguay | URY | 1 |
| 20 | Venezuela | VEN | 1 |
# Renombrar columna de codigo
spanish_language.rename({'Country code' : 'Nationality code'},
inplace = True,
axis = 1)
# Eliminar columna Country
spanish_language.drop('Country', inplace = True, axis = 1)
# Unir datos a dataset de inmigrantes_merge
inmigrantes_merge = inmigrantes_merge.merge(spanish_language, on = ['Nationality code'], how = 'left')
# Remplazar nulos con "0" en Spanish_language y pasar a tipo entero
inmigrantes_merge['Spanish language'].fillna(0, inplace = True)
# Pasar columna a tipo entero y luego a objeto
inmigrantes_merge['Spanish language'] = inmigrantes_merge['Spanish language'].astype(int).astype(object)
# Verificar correcta adicion
inmigrantes_merge.groupby('Nationality code')["Spanish language"].value_counts()
Nationality code Spanish language ARG 1 360 BGR 0 360 BRA 0 360 CHN 0 360 COL 1 360 CUB 1 360 DEU 0 360 DOM 1 360 DZA 0 360 ECU 1 360 FRA 0 360 GBR 0 360 HND 1 360 ITA 0 360 MAR 0 360 NIC 1 360 PAK 0 360 PER 1 360 PRT 0 360 PRY 1 360 ROU 0 360 RUS 0 360 SEN 0 360 UKR 0 360 USA 0 360 VEN 1 360 Name: count, dtype: int64
Pandemia y Post-pandemia
La variable categórica relacionada a la Pandemia señala si la presencia de restricciones sanitarias debidas al COVID durante los años 2020 y 2021 (Restricciones_pandemia = 1), y con ella se busca incluir el efecto de dichas restricciones en la variación del número de inmigrantes que llegaron a España.
Así mismo, también se incluye una variable "Año post_pandemia" para considerar la acumulación de inmigrantes durante las restricciones sanitarias entre 2020-2021, los cuáles no lograron viajar a España, y así incluir la particularidad del año 2022 al ser el primer año después de la flexibilización casi total de las restricciones.
# Añadir Variable Pandemia
inmigrantes_merge["Restricciones_pandemia"] = inmigrantes_merge["Year"].apply(lambda x: 1 if x==2020 or x==2021 else 0)
# Pasar a tipo objeto
inmigrantes_merge["Restricciones_pandemia"] = inmigrantes_merge["Restricciones_pandemia"].astype(object)
# Verificar adicion
inmigrantes_merge.groupby('Year')["Restricciones_pandemia"].value_counts()
Year Restricciones_pandemia 2008 0 624 2009 0 624 2010 0 624 2011 0 624 2012 0 624 2013 0 624 2014 0 624 2015 0 624 2016 0 624 2017 0 624 2018 0 624 2019 0 624 2020 1 624 2021 1 624 2022 0 624 Name: count, dtype: int64
# Añadir Variable Post-pandemia
inmigrantes_merge["Año post_pandemia"] = inmigrantes_merge["Year"].apply(lambda x: 1 if x==2022 else 0)
# Pasar a tipo objeto
inmigrantes_merge["Año post_pandemia"] = inmigrantes_merge["Año post_pandemia"].astype(object)
# Verificar adicion
inmigrantes_merge.groupby('Year')["Año post_pandemia"].value_counts()
Year Año post_pandemia 2008 0 624 2009 0 624 2010 0 624 2011 0 624 2012 0 624 2013 0 624 2014 0 624 2015 0 624 2016 0 624 2017 0 624 2018 0 624 2019 0 624 2020 0 624 2021 0 624 2022 1 624 Name: count, dtype: int64
inmigrantes_merge.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 9360 entries, 0 to 9359 Data columns (total 35 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Year 9360 non-null int64 1 Nationality code 9360 non-null object 2 Sex 9360 non-null object 3 Age group 9360 non-null object 4 Immigrant count 9360 non-null int64 5 Unemployment % 9360 non-null float64 6 Political and Violence Percentile 9360 non-null float64 7 Probability of dying young 9360 non-null float64 8 Regulatory Quality Percentile 9360 non-null float64 9 Rule of Law Percentile 9360 non-null float64 10 Voice and Accountability Percentile 9360 non-null float64 11 Salaried workers % 9360 non-null float64 12 GDP_growth 9360 non-null float64 13 Inflation_annual 9360 non-null float64 14 Liberal democracy index 9360 non-null float64 15 Deliberative democracy index 9360 non-null float64 16 Continent 9360 non-null object 17 Sub-region 9360 non-null object 18 Absence of Corruption 9360 non-null float64 19 Civil Liberties 9360 non-null float64 20 Educational equality 9360 non-null float64 21 Health equality 9360 non-null float64 22 Judicial accountability 9360 non-null float64 23 Public sector corrupt exchanges 9360 non-null float64 24 One-sided violence_deaths 9360 non-null int64 25 Non-state_deaths 9360 non-null int64 26 Intrastate_deaths 9360 non-null int64 27 Interstate_deaths 9360 non-null int64 28 Number of residents 9360 non-null int64 29 Political regime 9360 non-null int64 30 Homicide Rate 9024 non-null float64 31 Number of Turist 9360 non-null int64 32 Spanish language 9360 non-null object 33 Restricciones_pandemia 9360 non-null object 34 Año post_pandemia 9360 non-null object dtypes: float64(18), int64(9), object(8) memory usage: 2.5+ MB
# Pasar la variable de tipo de regimen politico a objeto
inmigrantes_merge['Political regime'] = inmigrantes_merge['Political regime'].astype(object)
# Construir matriz de correlacion de variable cuantitativas
plt.figure(figsize=(30,15))
sns.heatmap(round(inmigrantes_merge.iloc[:, 4:].corr(numeric_only = True), 2), annot = True, cmap= 'coolwarm')
<Axes: >
En base a los valores de correlaciones de Pearson, vemos:
inmigrantes_merge.drop(['Deliberative democracy index', 'Absence of Corruption', 'Civil Liberties', 'Educational equality',
'Regulatory Quality Percentile', 'Public sector corrupt exchanges','Voice and Accountability Percentile'],
axis = 1,
inplace = True)
Test de Normalidad
Evaluemos primero la normalidad de los datos de conteo inmigrantes en relacion a las distintos grupos de las variables categóricas con el test de Shapiro-Wilk con la finalidad de seleccionar un test paramétrico o no paramétrico para el contraste de hipótesis.
# Filtrar para las categorias "Both" de sexo y "All" de los grupos de edad para realizar pruebas
inmigrantes_tests = inmigrantes_merge[(inmigrantes_merge["Sex"] != "Both") & (inmigrantes_merge["Age group"] != "All")]
# Lista de variables categóricas a testear
categorical_vars = ["Sex", "Age group", "Political regime", "Continent", "Sub-region", "Spanish language"]
# Diccionario para almacenar los grupos
grupos = {}
# Agrupar datos por las variables categóricas
for var in categorical_vars:
grupos[var] = inmigrantes_tests.groupby([var])["Immigrant count"]
# Shapiro-Wilk test para cada grupo
for var in categorical_vars:
print(f'------------ {var} -------------')
for name, grupo in grupos[var]:
stat, p = stats.shapiro(grupo)
print(f'Group {name}: Statistics={round(stat, 4)}, p={round(p, 4)}')
print('')
------------ Sex ------------- Group Females: Statistics=0.5497, p=0.0 Group Males: Statistics=0.5113, p=0.0 ------------ Age group ------------- Group 0 - 14: Statistics=0.51, p=0.0 Group 15 - 24: Statistics=0.5864, p=0.0 Group 25 - 34: Statistics=0.5782, p=0.0 Group 35 - 44: Statistics=0.5288, p=0.0 Group 45 - 54: Statistics=0.5587, p=0.0 Group 55 - 64: Statistics=0.5923, p=0.0 Group 65+: Statistics=0.5947, p=0.0 ------------ Political regime ------------- Group 0: Statistics=0.9071, p=0.0 Group 1: Statistics=0.6338, p=0.0 Group 2: Statistics=0.7825, p=0.0 Group 3: Statistics=0.6483, p=0.0 Group 6: Statistics=0.4623, p=0.0 Group 7: Statistics=0.6851, p=0.0 ------------ Continent ------------- Group Africa: Statistics=0.5627, p=0.0 Group America: Statistics=0.5001, p=0.0 Group Asia: Statistics=0.8624, p=0.0 Group Europe: Statistics=0.5974, p=0.0 ------------ Sub-region ------------- Group Africa: Statistics=0.5627, p=0.0 Group Asia: Statistics=0.8624, p=0.0 Group Central America and Caribbean: Statistics=0.6921, p=0.0 Group European Union: Statistics=0.6436, p=0.0 Group North America: Statistics=0.8568, p=0.0 Group Rest of Europe: Statistics=0.4896, p=0.0 Group South America: Statistics=0.5279, p=0.0 ------------ Spanish language ------------- Group 0: Statistics=0.5476, p=0.0 Group 1: Statistics=0.5098, p=0.0
A partir de los resultados de p-valor, rechazamos la hipotesis nula H0 con un nivel de confianza de 95% (p-valor < 0.05), es decir, los datos no siguen una disibución normal; resultado que se esperaba considerando nuestro análisis inicial de los datos de inmigración durante la Etapa 1.
En consecuencia, usaremos el test no paramétricos U de Mann-Whitney (para dos grupos) y Kruskal-Wallis para aquellas variables con múltiples grupos.
Prueba U de Mann-Whitney y Prueba de Kruskal-Wallis
# Variables para Mann-Whitney U test (dos grupos)
mann_whitney_vars = {
"Sex": ["Males", "Females"],
"Spanish language": [0, 1]
}
# Variables para Kruskal-Wallis test (mas de dos grupo)
kruskal_wallis_vars = {
"Age group": ['0 - 14', '15 - 24', '25 - 34', '35 - 44', '45 - 54', '55 - 64', '65+'],
"Political regime": [0, 1, 2, 3, 6, 7],
"Continent": ['Africa', 'Asia', 'America', 'Europe'],
"Sub-region": ['Africa', 'Asia', 'Central America and Caribbean', 'European Union', 'North America', 'Rest of Europe', 'South America']
}
# Iterar variables con dos grupos para la prueba de Mann-Whitney
for var, groups in mann_whitney_vars.items():
print(f'------------------ Variable "{var}" -------------------- \n')
stat, p = stats.mannwhitneyu(inmigrantes_merge[inmigrantes_merge[var] == groups[0]]["Immigrant count"],
inmigrantes_merge[inmigrantes_merge[var] == groups[1]]["Immigrant count"])
print(f'Prueba U de Mann-Whitney: Statistics={round(stat, 4)}, p={round(p, 4)} \n')
# Iterar variables con más de dospara la prueba de Kruskal-Wallis test
for var, groups in kruskal_wallis_vars.items():
print(f'------------------ Variable "{var}" -------------------- \n')
group_data = [inmigrantes_merge[inmigrantes_merge[var] == group]["Immigrant count"] for group in groups]
stat, p = stats.kruskal(*group_data)
print(f'Prueba Kruskal-Wallis: Statistics={round(stat, 4)}, p={round(p, 4)} \n')
------------------ Variable "Sex" -------------------- Prueba U de Mann-Whitney: Statistics=4641572.5, p=0.0015 ------------------ Variable "Spanish language" -------------------- Prueba U de Mann-Whitney: Statistics=10816393.0, p=0.0004 ------------------ Variable "Age group" -------------------- Prueba Kruskal-Wallis: Statistics=2726.2587, p=0.0 ------------------ Variable "Political regime" -------------------- Prueba Kruskal-Wallis: Statistics=365.6376, p=0.0 ------------------ Variable "Continent" -------------------- Prueba Kruskal-Wallis: Statistics=116.0261, p=0.0 ------------------ Variable "Sub-region" -------------------- Prueba Kruskal-Wallis: Statistics=260.0816, p=0.0
Para todas las variables rechazamos la hipótesis nula H0 (p-valor < 0.05), es decir, la número de inmigracion de mujeres y hombres difieren y, para las variables con más de dos grupos, al menos dos de ellos difieren. En consecuencia, no removeremos ninguna de las variables categóricas de nuestros datos.
Veamos la distribución con boxplots para las dos variables copn solo 2 grupos: "Sex" y "Spanish language".
# Función para graficar distribucion de datos de cantidad de inmigrantes en boxplots segun grupos de variables categóricas
def boxplot_grupos(datos, variable):
"""
Función que realiza un boxplot horizontal de número de inmigrantes por grupos
con la librería Altair a partir de los siguientes parámetros:
- datos: origen de los datos
- variable (string): variable categórica (ej: 'Age group')
"""
return alt.Chart(datos, height=30, width=1000).mark_boxplot().encode(
x=alt.X('Immigrant count:Q', title="Número de Inmigrantes"),
row=alt.Row(variable, header=alt.Header(labelAngle=-360, labelAlign='left')),
tooltip=["Nationality code", 'Year']
).properties(title=f'{variable}')
# Boxplots por grupos de las variables "Sex" y "Spanish language"
boxplot_grupos(inmigrantes_tests, "Sex").display()
boxplot_grupos(inmigrantes_tests, "Spanish language").display()
A través de los boxplots es dificil establecer diferencias en la tendencia central entre los sexos y países con el castellano como idioma oficial. En el caso se sexo, puede deberse a que se observa una mayor disperción en los datos de cantidad de inmigrantes hombres, similar a lo que se observa en el grupo de idioma castellano.
Ahora bien, veamos cuales grupon difieren entre sí para las variables que presentan mas de 2 grupos usando el test de Dunn de comparasión multiple:
Simplifiquemos la vista de resultados de la matriz de p-valores para una comparación mas sencilla.
# Funcion para simplificar los la matriz de resultados de la prueba de Dunn e indicar diferencia "Sí" o "No"
def simplificar_resultados_dunn(dunn_resultados):
simplified_results = dunn_resultados.stack().reset_index()
simplified_results.columns = ['Grupo 1', 'Grupo 2', 'p-valor']
# Evitar que se repitan grupos ya comparados
simplified_results = simplified_results[simplified_results['Grupo 1'] != simplified_results['Grupo 2']]
simplified_results = simplified_results[simplified_results['Grupo 1'] < simplified_results['Grupo 2']]
# Agregar columna para especificar si hay o no diferencias significativas
simplified_results['Diferencias?'] = simplified_results['p-valor'].apply(lambda x: 'Si' if x < 0.05 else 'No')
return simplified_results
# Lista de variables
variables = ['Age group', 'Political regime', 'Continent', 'Sub-region']
# Realizar test de Dunn en cada variable, mostrar resultados de las comparasiones pareadas y exportar tabla
with pd.option_context('expand_frame_repr', False): # expandir las columnas del output
for var in variables:
print(f'------------------ Variable "{var}" -------------------- \n')
dunn_resultados = sp.posthoc_dunn(inmigrantes_tests,
val_col="Immigrant count",
group_col=var,
p_adjust='bonferroni')
print('Prueba de comparación múltiple de Dunn: \n', simplificar_resultados_dunn(dunn_resultados), "\n")
# Exportar resultados como csv
simplificar_resultados_dunn(dunn_resultados).to_csv(f"../14 - Exports (resultados prueba de dunn)/{var}_resultados_dunn.csv",
index=False,
encoding = 'utf-8')
------------------ Variable "Age group" --------------------
Prueba de comparación múltiple de Dunn:
Grupo 1 Grupo 2 p-valor Diferencias?
1 0 - 14 15 - 24 1.665376e-08 Si
2 0 - 14 25 - 34 1.306032e-29 Si
3 0 - 14 35 - 44 1.000000e+00 No
4 0 - 14 45 - 54 2.604809e-20 Si
5 0 - 14 55 - 64 1.580498e-73 Si
6 0 - 14 65+ 3.218532e-110 Si
9 15 - 24 25 - 34 1.262778e-06 Si
10 15 - 24 35 - 44 3.759252e-05 Si
11 15 - 24 45 - 54 3.129615e-54 Si
12 15 - 24 55 - 64 1.019143e-130 Si
13 15 - 24 65+ 1.972534e-178 Si
17 25 - 34 35 - 44 4.420449e-23 Si
18 25 - 34 45 - 54 1.109330e-97 Si
19 25 - 34 55 - 64 1.017288e-194 Si
20 25 - 34 65+ 3.724038e-252 Si
25 35 - 44 45 - 54 1.835213e-26 Si
26 35 - 44 55 - 64 7.314785e-85 Si
27 35 - 44 65+ 5.203596e-124 Si
33 45 - 54 55 - 64 4.458760e-17 Si
34 45 - 54 65+ 1.113573e-36 Si
41 55 - 64 65+ 7.395364e-04 Si
------------------ Variable "Political regime" --------------------
Prueba de comparación múltiple de Dunn:
Grupo 1 Grupo 2 p-valor Diferencias?
1 0 1 5.797419e-01 No
2 0 2 3.210212e-17 Si
3 0 3 4.248195e-04 Si
4 0 6 7.591952e-02 No
5 0 7 1.000000e+00 No
8 1 2 6.458774e-13 Si
9 1 3 3.568171e-13 Si
10 1 6 3.733542e-09 Si
11 1 7 3.723511e-01 No
15 2 3 1.941724e-51 Si
16 2 6 6.597457e-47 Si
17 2 7 1.306699e-28 Si
22 3 6 1.231845e-01 No
23 3 7 4.400942e-18 Si
29 6 7 9.474825e-14 Si
------------------ Variable "Continent" --------------------
Prueba de comparación múltiple de Dunn:
Grupo 1 Grupo 2 p-valor Diferencias?
1 Africa America 1.000000e+00 No
2 Africa Asia 1.000000e+00 No
3 Africa Europe 1.622303e-12 Si
6 America Asia 1.000000e+00 No
7 America Europe 6.567824e-21 Si
11 Asia Europe 1.564577e-10 Si
------------------ Variable "Sub-region" --------------------
Prueba de comparación múltiple de Dunn:
Grupo 1 Grupo 2 p-valor Diferencias?
1 Africa Asia 1.000000e+00 No
2 Africa Central America and Caribbean 8.473527e-03 Si
3 Africa European Union 5.513440e-12 Si
4 Africa North America 4.335915e-03 Si
5 Africa Rest of Europe 3.437238e-06 Si
6 Africa South America 4.321137e-05 Si
9 Asia Central America and Caribbean 1.339112e-01 No
10 Asia European Union 3.131845e-10 Si
11 Asia North America 2.679378e-02 Si
12 Asia Rest of Europe 9.000989e-06 Si
13 Asia South America 1.362301e-04 Si
17 Central America and Caribbean European Union 6.837387e-33 Si
18 Central America and Caribbean North America 1.000000e+00 No
19 Central America and Caribbean Rest of Europe 1.363378e-18 Si
20 Central America and Caribbean South America 3.059028e-20 Si
25 European Union North America 4.315470e-17 Si
26 European Union Rest of Europe 1.000000e+00 No
27 European Union South America 1.389210e-02 Si
33 North America Rest of Europe 2.579185e-12 Si
34 North America South America 3.186092e-11 Si
41 Rest of Europe South America 1.000000e+00 No
Para los grupos de edades, observamos que únicamente los grupos de 0-14 años y 35-44 años no tienen diferencias significativas, el resto sí. Veamos la distribución de inmigrantes por grupo con boxplots:
# Boxplots de Cantidad de Inmigrantes por grupo de edad
boxplot_grupos(inmigrantes_tests, "Age group").display()
Es dificil observar tendencias debido a la cantidad de datos atípicos, pero si nos enfocamos en las cajas y bigotes de las cajas junto a la concentración de datos atípicos, puede distinguirse la diferencias en la tendencia central detectada por el test de Dunn para casi todos los grupos, menos entre 0-14 y 35-44 años.
En cuanto a los tipos de régimen político, resalta el régimen tipo 2 (autocracias multipartidistas sin ejecutivo electo) es significativamente diferente al resto, resultado que se refleja claramente en el boxplot (ver gráfico abajo). De forma similar, el régimen tipo 3 (autocracias multipartidistas) también presentó diferencias con los demás tipos de regímenes, exceptuando el tipo 6 (democracias electorales).
# Boxplots de Cantidad de Inmigrantes por régimen político
boxplot_grupos(inmigrantes_tests, "Political regime").display()
El continente europeo fue el único que presentó diferencias significativas con el resto de los continentes.
En contraste con los continentes, las subregiones presentan una mayor cantidad de diferencias significativas Vemos a América del Norte que se diferencia de todos menos con el Caribe-Centro América. De forma similar, la UE y América del Sur también difieren con todos, exceptuando a “el resto de Europa”.
# Boxplots de Cantidad de Inmigrantes por continente
boxplot_grupos(inmigrantes_tests, "Continent").display()
# Boxplots de Cantidad de Inmigrantes por sub-región
boxplot_grupos(inmigrantes_tests, "Sub-region").display()
A razón estas observaciones, no se removeran ninguna de las variables categóricas del conjunto de datos para la construcción del modelo de machine learning (referirse a los notebooks de "Etapa 4").
# Exportar conjunto de datos final con todas las variables seleccionadas
inmigrantes_merge.to_csv("../13 - Exports (preprocesamiento)/inmigrantes_merge.csv", index = False)